package com.serverTechnology.resource.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.serverTechnology.resource.controller.DeviceController;
import com.serverTechnology.resource.entity.DeviceEntity;
import com.serverTechnology.resource.entity.DispositionEntity;
import com.serverTechnology.resource.entity.ManagementEntity;
import com.serverTechnology.resource.entity.dto.*;
import com.serverTechnology.resource.entity.vo.DeviceDetailVo;
import com.serverTechnology.resource.mapper.DeviceMapper;
import com.serverTechnology.resource.mapper.ManagementMapper;
import com.serverTechnology.resource.resourceEnum.DispositionEnum;
import com.serverTechnology.resource.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.serverTechnology.resource.service.IDispositionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 设备类型表 服务实现类
 * </p>
 *
 * @author 王烁
 * @since 2024-07-28
 */
@Service("DeviceServiceImpl")
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, DeviceEntity> implements IDeviceService {

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private ManagementMapper managementMapper;

    @Resource(name = "DispositionServiceImpl")
    private IDispositionService iDispositionService;

    /**
     * 添加设备及关联的处置信息到数据库。
     *
     * @param device 包含设备信息及处置信息的数据传输对象
     * @throws IllegalArgumentException 如果 device 参数为 null
     */
    @Override
    public void add(DeviceDto device) {
        // 创建一个新的设备实体对象
        DeviceEntity deviceEntity = new DeviceEntity();
        // 将传入的设备数据传输对象的属性复制到设备实体对象中
        BeanUtil.copyProperties(device, deviceEntity);
        // 向设备表中插入设备信息

        try {
            deviceMapper.insert(deviceEntity);
        } catch (Exception e) {
            throw new RuntimeException("编号不能相同");
        }
        // 准备一个空的处置信息列表
        List<DispositionAddDto> list = new ArrayList<>();
        // 将设备的处置信息数据传输对象列表复制到 dispositionAddDtos 变量中
        List<DispositionAddDto> dispositionAddDtos = device.getDispositionAddDtos();
        // 遍历处置信息数据传输对象列表
        for (DispositionAddDto dispositionAddDto : dispositionAddDtos) {
            // 设置处置信息数据传输对象中的设备ID为新插入的设备实体对象的ID
            dispositionAddDto.setDeviceId(deviceEntity.getId());
            // 将设置好的处置信息数据传输对象添加到 list 列表中
            list.add(dispositionAddDto);
        }
        // 将 list 列表中的处置信息数据传输对象列表转换为处置信息实体列表
        List<DispositionEntity> dispositionEntities = BeanUtil.copyToList(list, DispositionEntity.class);
        // 调用处置信息服务的批量保存方法，将处置信息实体列表保存到数据库中
        try {
            iDispositionService.saveBatch(dispositionEntities);
        } catch (Exception e) {
            throw new RuntimeException("编号不能相同");
        }
    }

    /**
     * 分页查询所有设备信息及其关联的处置信息。
     *
     * @param detail 包含设备查询条件的数据传输对象
     * @return 分页查询结果，包含设备实体列表及其关联的处置信息
     */
    @Override
    public PageResult<DeviceEntity> pageAll(DevicePageDto detail) {
        // 创建查询条件包装器
        LambdaQueryWrapper<DeviceEntity> wrapper = new LambdaQueryWrapper<>();

        // 设置查询条件：设备分类为指定的设备区分
        wrapper.eq(DeviceEntity::getDeviceDistinguish, detail.getDeviceDistinguish());
        if (StringUtils.isNotEmpty(detail.getDeviceName())) {
            // 设置查询条件：设备名称为指定的设备名称
            wrapper.like(DeviceEntity::getDeviceName, detail.getDeviceName());
        }
        // 调用 MyBatis-Plus 的分页查询方法，使用默认分页参数和查询条件进行查询
        Page<DeviceEntity> devicePage = this.page(PageFactory.defaultPage(), wrapper);

        // 获取查询结果中的设备实体列表
        List<DeviceEntity> deviceEntities = devicePage.getRecords();

        // 提取所有设备的ID列表
        List<Long> deviceIds = deviceEntities.stream()
                .map(DeviceEntity::getId)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(deviceIds)) {
            // 查询处置信息的条件包装器
            LambdaQueryWrapper<DispositionEntity> dispositionWrapper = new LambdaQueryWrapper<>();

            // 设置处置信息查询条件：设备ID在上面查询到的所有设备ID列表中
            dispositionWrapper.in(DispositionEntity::getDeviceId, deviceIds);

            // 查询符合条件的处置信息列表
            List<DispositionEntity> dispositionEntities = iDispositionService.list(dispositionWrapper);
            // 将处置信息按设备ID分组，以便后续组装数据
            Map<Long, List<DispositionEntity>> dispositionMap = dispositionEntities.stream()
                    .collect(Collectors.groupingBy(DispositionEntity::getDeviceId));
            // 遍历设备实体列表，为每个设备设置其关联的处置信息
            for (DeviceEntity deviceEntity : deviceEntities) {
                // 获取当前设备ID
                Long deviceId = deviceEntity.getId();

                // 如果处置信息Map中包含当前设备ID的记录
                if (dispositionMap.containsKey(deviceId)) {
                    // 获取当前设备的处置信息列表
                    List<DispositionEntity> relatedDispositions = dispositionMap.get(deviceId);

                    // 将处置信息名称存入设备实体中的字段（假设设备实体有相应的字段存放处置信息名称）
                    List<String> dispositionNames = relatedDispositions.stream()
                            .map(DispositionEntity::getDispositionName)
                            .collect(Collectors.toList());

                    deviceEntity.setDispositionName(dispositionNames);
                } else {
                    // 如果当前设备没有关联的处置信息，设置一个空列表或者做其他处理
                    deviceEntity.setDispositionName(Collections.emptyList());
                }
            }

            // 将处理后的设备列表设置回分页对象中
            devicePage.setRecords(deviceEntities);
        }
        // 将查询结果转换为自定义的分页结果对象，并返回
        return PageResultFactory.createPageResult(devicePage);
    }


    /**
     * 根据设备ID查询设备详细信息及其关联的处置信息。
     *
     * @param id 设备ID
     * @return 包含设备详细信息及处置信息的视图对象
     */
    @Override
    public DeviceDetailVo detail(Long id, Integer type) {
        // 创建设备详细信息视图对象
        DeviceDetailVo deviceDetailVo = new DeviceDetailVo();
        // 创建查询条件包装器
        LambdaQueryWrapper<DeviceEntity> wrapper = new LambdaQueryWrapper<>();
        // 设置查询条件：设备ID等于指定的ID
        wrapper.eq(DeviceEntity::getId, id);
        // 根据查询条件查询单个设备实体对象
        DeviceEntity deviceEntity = deviceMapper.selectOne(wrapper);
        // 将设备实体对象的属性复制到设备详细信息视图对象中
        BeanUtils.copyProperties(deviceEntity, deviceDetailVo);

        // 创建处置信息查询条件包装器
        LambdaQueryWrapper<DispositionEntity> dispositionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 设置处置信息查询条件：设备ID等于设备详细信息视图对象中的ID
        dispositionLambdaQueryWrapper.eq(DispositionEntity::getDeviceId, deviceDetailVo.getId());
        // 查询符合条件的处置信息列表
        List<DispositionEntity> dispositionEntityList = iDispositionService.list(dispositionLambdaQueryWrapper);
        // 创建字符串列表，用于存储处置名称
        List<String> strings = new ArrayList<>();
        if (type == 1) {

            // 如果查询到处置信息，则设置到设备详细信息视图对象中
            if (!dispositionEntityList.isEmpty()) {
                deviceDetailVo.setDispositionEntityList(dispositionEntityList);
                // 遍历处置信息列表，将处置名称添加到字符串列表中
                for (DispositionEntity dispositionEntity : dispositionEntityList) {
                    strings.add(dispositionEntity.getDispositionName());
                }

            }
        } else if (type == 2) {
            // 如果type为2，调用getFuziMenuTreeWithoutChildren()方法获取数据
            List<DispositionEntity> menuItems = getFuziMenuTreeWithoutChildren();

            // 只保留与deviceDetailVo.getId()相同的id参数
            List<DispositionEntity> filteredItems = menuItems.stream()
                    .filter(item -> item.getDeviceId().equals(deviceDetailVo.getId()))
                    .collect(Collectors.toList());

            deviceDetailVo.setDispositionEntityList(filteredItems);
        }
        // 返回包含设备详细信息及处置信息的视图对象
        return deviceDetailVo;
    }

    public List<DispositionEntity> getFuziMenuTreeWithoutChildren() {
        QueryWrapper<DispositionEntity> fuzi = new QueryWrapper<>();
        List<DispositionEntity> menuList = iDispositionService.list(fuzi);
        return buildMenuTree(menuList); // 构建菜单树
    }

    // 构建父子级菜单树
    public List<DispositionEntity> buildMenuTree(List<DispositionEntity> menuList) {
        Map<Long, DispositionEntity> menuMap = new HashMap<>();

        // 将菜单放入Map中，以菜单ID作为键
        for (DispositionEntity menu : menuList) {
            menuMap.put(menu.getId(), menu);
        }

        // 遍历菜单列表，将子菜单添加到对应的父菜单的children属性中
        List<DispositionEntity> treeMenu = new ArrayList<>();
        for (DispositionEntity menu : menuList) {
            Long parentId = menu.getFid();
            if (parentId == null || parentId == 0) {
                // 顶级菜单
                treeMenu.add(menu);
            } else {
                // 子菜单
                DispositionEntity parentMenu = menuMap.get(parentId);
                if (parentMenu != null) {
                    if (parentMenu.getChildren() == null) {
                        parentMenu.setChildren(new ArrayList<>());
                    }
                    parentMenu.getChildren().add(menu);
                }
            }
        }

        // 对顶级菜单及其子菜单按照 display_order 排序
        sortTreeMenu(treeMenu);
        return treeMenu;
    }

    // 递归排序树形结构的菜单
    private void sortTreeMenu(List<DispositionEntity> treeMenu) {
        for (DispositionEntity menu : treeMenu) {
            if (menu.getChildren() != null && !menu.getChildren().isEmpty()) {
                // 递归排序子菜单
                sortTreeMenu(menu.getChildren());
            }
        }
    }

    /**
     * 删除设备及其关联的配置信息。
     *
     * @param id 设备ID
     */
    @Transactional
    @Override
    public void deleteDevice(Long id) {
        Long l = managementMapper.selectCount(new LambdaQueryWrapper<ManagementEntity>().eq(ManagementEntity::getDeviceId, id));
        if (l > 0){
            throw new RuntimeException("该设备已被绑定，无法删除");
        }
        // 删除关联的配置信息（DispositionEntity）
        LambdaQueryWrapper<DispositionEntity> dispositionQuery = new LambdaQueryWrapper<>();
        dispositionQuery.eq(DispositionEntity::getDeviceId, id);
        iDispositionService.remove(dispositionQuery);

        // 删除设备信息（DeviceEntity）
        LambdaQueryWrapper<DeviceEntity> deviceQuery = new LambdaQueryWrapper<>();
        deviceQuery.eq(DeviceEntity::getId, id);
        deviceMapper.delete(deviceQuery);
    }


    /**
     * 根据给定的设备信息更新设备及其关联的配置信息。
     *
     * @param device 包含更新数据的设备DTO对象
     */
    @Override
    public void updateByDevice(DeviceUpdateDto device) {
        // 获取设备的子对象列表
        List<DispUpdateDto> children = device.getChildren();
        // 用于存储需要删除的ID列表
        List<Long> idsToRemove = new ArrayList<>();

        // 遍历子对象，收集需要删除的ID
        for (DispUpdateDto child : children) {
            // 检查子对象的 isDel 属性是否为 true
            if (child.getIsDel()) {
                // 如果是 true，则将子对象的 ID 添加到 idsToRemove 列表中
                idsToRemove.add(child.getId());
            }
        }

            // 如果有需要删除的ID，则执行删除操作
        if (!idsToRemove.isEmpty()) {
            // 构造 LambdaQueryWrapper，使用 in 条件删除多个ID对应的记录
            LambdaQueryWrapper<DispositionEntity> dispositionEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dispositionEntityLambdaQueryWrapper.in(DispositionEntity::getId, idsToRemove);
//            iDispositionService.remove(dispositionEntityLambdaQueryWrapper);
            iDispositionService.removeBatchByIds(idsToRemove);
        }

        // 创建一个新的DeviceEntity对象并复制设备信息
        DeviceEntity deviceEntity = new DeviceEntity();
        BeanUtils.copyProperties(device, deviceEntity);

        // 构建查询条件，更新设备信息
        LambdaQueryWrapper<DeviceEntity> deviceUpdateQuery = new LambdaQueryWrapper<>();
        deviceUpdateQuery.eq(DeviceEntity::getId, device.getId());
        try {
            deviceMapper.update(deviceEntity, deviceUpdateQuery);
        } catch (Exception e) {
            throw new RuntimeException("设备更新失败：" + e.getMessage());
        }

        // 处理子对象的配置信息
        List<DispositionEntity> dispositionEntityList = children.stream()
                .filter(child -> child.getId() != null && child.getId() != 0) // 过滤掉id为null或0的子对象
                .map(child -> {
                    // 创建一个新的DispositionEntity对象并复制子对象的信息
                    DispositionEntity dispositionEntity = new DispositionEntity();
                    BeanUtils.copyProperties(child, dispositionEntity);
                    dispositionEntity.setDeviceId(device.getId()); // 设置关联的设备ID
                    return dispositionEntity;
                })
                .collect(Collectors.toList());

        // 批量保存或更新子对象的配置信息
        if (!dispositionEntityList.isEmpty()) {
            try {
                iDispositionService.saveOrUpdateBatch(dispositionEntityList);
            } catch (Exception e) {
                throw new RuntimeException("编号不能相同");
            }
        }
    }



}

